home *** CD-ROM | disk | FTP | other *** search
- unit DBFTable;
-
- (*
-
- ***************************************************************
- * *
- * DBFTable compoment *
- * *
- * (c) 1997 Reinhard Kalinke *
- * *
- * r_kalinke@compuserve.com *
- * *
- ***************************************************************
-
- This TTable descendant adds means to handle missing MDX and DBT
- files with dBase tables. It also implements autosaving changes
- to disk. However, this will not have the desired effect as all
- BDE versions (tested up to 4.01) do not implement that feature
- correctly.
-
- *)
-
- interface
-
- uses
- SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
- Forms, Dialogs, DB, DBTables, BDEDoRxS, DBITypes;
-
- type
- TDBFAtDBTMissing = (atdOpenWithout,atdOpenError,atdRemoveFields);
- TDBFAtMDXMissing = (atmOpenReadOnly,atmOpenError,atmDetachMDX);
- TDBFOpenFailType = (ofNone,ofMDXMissing,ofDBTMissing);
- TDBFOpenFailure = procedure(Sender: TObject;
- FailType: TDBFOpenFailType) of object;
- TDBFFailRec = record
- FailType: TDBFOpenFailType;
- DBTAction: TDBFAtDBTMissing;
- MDXAction: TDBFAtMDXMissing;
- end;
-
- TDBFTable = class(TTable)
- private
- FFailRec: TDBFFailRec;
- FOnOpenFailure: TDBFOpenFailure;
- FInputDesc: cbInputDesc;
- FAutoSaveChanges: boolean;
- procedure SetAtDBTMissing(Value: TDBFAtDBTMissing);
- procedure SetAtMDXMissing(Value: TDBFAtMDXMissing);
- procedure SetAutoSaveChanges(Value: boolean);
- protected
- procedure DoBeforeOpen; override;
- procedure DoAfterOpen; override;
- procedure DoAfterPost; override;
- procedure DoAfterDelete; override;
- function CreateHandle: hDBICur; override;
- public
- constructor Create(AOwner: TComponent); override;
- published
- property AtDBTMissing: TDBFAtDBTMissing
- read FFailRec.DBTAction write SetAtDBTMissing default atdOpenWithout;
- property AtMDXMissing: TDBFAtMDXMissing
- read FFailRec.MDXAction write SetAtMDXMissing default atmDetachMDX;
- property AutoSaveChanges: boolean
- read FAutoSaveChanges write SetAutoSaveChanges default True;
- property OnOpenFailure: TDBFOpenFailure
- read FOnOpenFailure write FOnOpenFailure;
- end;
-
- procedure Register;
-
- implementation
-
- uses DBIProcs, DBIErrs;
-
- {$S-} {no stack checking in a callback, at least with 16bit} (**)
- function InputRequestCallback(ecbType:CBType;
- Failure:Longint; var CBInfo:pointer):CBRType;
- {$IFDEF WIN32}stdcall;{$ELSE}export;{$ENDIF}
- var InputDesc: pcbInputDesc;
- FailType: TDBFOpenFailType;
- FailRec: TDBFFailRec;
- begin
- Result := cbrUSEDEF;
- if (ecbType = CBType(cbINPUTREQ)) then
- begin
- InputDesc := pcbInputDesc(@CBInfo);
- FailRec := TDBFFailRec(pointer(Failure)^);
- if InputDesc^.eCbInputId = cbiMDXMISSING then
- begin
- FailType := ofMDXMissing;
- InputDesc^.iSelection := succ(ord(FailRec.MDXAction));
- end;
- if InputDesc^.eCbInputId = cbiDBTMISSING then
- begin
- FailType := ofDBTMissing;
- InputDesc^.iSelection := succ(ord(FailRec.DBTAction));
- end;
- if (FailType <> ofNone) then
- begin
- TDBFFailRec(pointer(Failure)^).FailType := FailType;
- InputDesc^.bSave := False;
- Result := cbrCHKINPUT;
- end;
- end;
- end;
- {S+} {stack checking on again} (**)
-
- constructor TDBFTable.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FFailRec.DBTAction := atdOpenWithout;
- FFailRec.MDXAction := atmDetachMDX;
- FAutoSaveChanges := True;
- end;
-
- procedure TDBFTable.DoBeforeOpen;
- var r: DBIResult;
- begin
- inherited DoBeforeOpen;
- DBIRegisterCallback( nil,
- CBType(cbINPUTREQ),
- longint(@FFailRec),
- sizeof(cbINPUTDesc),
- @FInputDesc,
- {$IFDEF WIN32}
- @InputRequestCallBack);
- {$ELSE}
- InputRequestCallBack);
- {$ENDIF}
- end;
-
- function TDBFTable.CreateHandle: hDBICur;
- var BDEError: DBIResult;
- i: integer;
- begin
- try try
- Result := inherited CreateHandle;
- except
- on E:EDBEngineError do
- begin
- for i:=0 to pred(E.ErrorCount) do
- begin
- BDEError := E.Errors[i].ErrorCode;
- if (BDEError = DBIERR_BLOBFILEMISSING) then
- FFailRec.FailType := ofDBTMissing;
- if (BDEError = DBIERR_NOSUCHINDEX) then
- FFailRec.FailType := ofMDXMissing;
- end;
- if (FFailRec.FailType <> ofNone) then
- Sysutils.Abort
- else raise;
- end;{}
- end;
- finally
- DBIRegisterCallback(nil, CBType(cbINPUTREQ),
- 0, 0, nil, nil);
- DBIUseIdleTime;
- if ((FFailRec.FailType = ofDBTMissing)
- and (FFailRec.DBTAction = atdOpenError))
- or ((FFailRec.FailType = ofMDXMissing)
- and (FFailRec.MDXAction = atmOpenError))
- and Assigned(FOnOpenFailure) then
- FOnOpenFailure(Self, FFailRec.FailType);
- FFailRec.FailType := ofNone;
- end;
- end;
-
- procedure TDBFTable.DoAfterOpen;
- begin
- if (FFailRec.FailType <> ofNone)
- and Assigned(FOnOpenFailure) then
- FOnOpenFailure(Self, FFailRec.FailType);
- FFailRec.FailType := ofNone;
- inherited DoAfterOpen;
- end;
-
- procedure TDBFTable.DoAfterPost;
- begin
- if FAutoSaveChanges then
- DBISaveChanges(Handle);
- inherited DoAfterPost;
- end;
-
- procedure TDBFTable.DoAfterDelete;
- begin
- if FAutoSaveChanges then
- DBISaveChanges(Handle);
- inherited DoAfterDelete;
- end;
-
- procedure TDBFTable.SetAtDBTMissing(Value: TDBFAtDBTMissing);
- begin
- if (FFailRec.DBTAction <> Value) then
- FFailRec.DBTAction := Value;
- end;
-
- procedure TDBFTable.SetAtMDXMissing(Value: TDBFAtMDXMissing);
- begin
- if (FFailRec.MDXAction <> Value) then
- FFailRec.MDXAction := Value;
- end;
-
- procedure TDBFTable.SetAutoSaveChanges(Value: boolean);
- begin
- if (FAutoSaveChanges <> Value) then
- FAutoSaveChanges := Value;
- end;
-
- {-----------------}
-
- procedure Register;
- begin
- RegisterComponents('DBAddOns', [TDBFTable]);
- end;
-
- end.
-